Backup & Restore
Drop-In 4th Dimension Utilities

Written By
Kenneth A. Craig
195 10th St. NW
Atlanta, GA  30318

GEnie : K.CRAIG
Compuserve : 76210,16

THESE PROCEDURES ARE NOT FREE !!!
YOU ARE REQUIRED TO CONTACT ME IN SOME WAY (SEND ME A POSTCARD, A LETTER, A DISK, A PEN OR PENCIL, LOTS OF MONEY, OR ANYTHING USEFUL TO LET ME KNOW THAT SOMEONE OUT THERE APPRECIATES MY SIMPLE GESTURES TO HELP OTHER PROGRAMMERS.
I AM A POOR, STARVING STUDENT AT GEORGIA TECH (GO JACKETS!!!) AND CAN USE ANY HELPFUL INFORMATION, ADVICE, CARS, ETC. TO GET ME THROUGH THESE LEAN YEARS.
Also, please give me credit for these procedures if you use them commercially (just leave the comments in). 
There is no guarantee of the performance of these procedures, written or implied, and neither I, nor Information Management, Inc., nor anyone associated with us assume any liability for their performance.  The archiving and subsequent restoration of data is a very dangerous procedure which can result in data loss and lost time (everybody knows that), these procedures are intended to ease the burden of writing custom made backup and restore routines for each database created.

Enough of the legal mumbo jumbo, what does it really do ?

BACKUP and RESTORE are two relatively simple procedures for 4D which can just be dropped into any 4D database (along with a small proc.ext file) to allow you, with no customization necessary, to archive all data for that database into one file and restore it at a later date.  They use three external procedures provided by Acius in their December 1987 developer mailings (now available on BBS's everywhere).  
	DataBaseName - gets the name of the current database
	GetNumFiles - gets the total number of files in the database
	GetFileNames - gets the name of a file from within the database
These are included in the file proc.ext which should be dropped into the database folder before the procedures below are pasted into a 4D global procedures.  You can also move these into the database.res file using 4D External Mover provided with 4th Dimension.
Just paste these procedures into 4D globals and supply menu commands (Backup Database, and Restore Database From Backup) which call the respective procedures.  You should provide password protection for RESTORE to only the highest level user.

Possible modifications ...
Removal of the safety feature of saving the number of files in the database.  This would allow you to transfer all data from one database into an updated version in which files have been added or deleted from the structure.
Removal of the database name from the backup.  This, along with the above change, would let you move data from two completely different databases that share some subset of each other's structure (exactly !!!).
More powerful options dealing with deleting or appending to current data, or deleting only duplicates, etc.  I have no need for it so I haven't even attempted it.

Once more I beg of you to send me some correspondence, physical or electronic telling me in what kind of database you use these in, how you like it, etc., send me some of your own work, from 4D or other things, send me some compensation or advice or anything useful, (beggars can't be choosers).

-------------------------------------------------------------
BACKUP
-------------------------------------------------------------
   `**********************************
   `BACKUP Backs Up All Files In The Database
   `Kenneth A. Craig
   `Information Management Inc.
   `376 Oakdale Rd
   `Atlanta, GA  30307
   `(404) 523-1132
   `CIS 76210,16
   `GEnie K.CRAIG
   `Be sure you have the externals DataBaseName, GetNumFiles, GetFileName
   `   available in either the System Folder or the Application folder as "proc.ext"
   `   or installed into the Database.res file.
   `------------------------------------------------
   `NOTE : DO NOT rename the database or any files, or
   `      change the fields in any of the files or the the
   `      file will not RESTORE properly.
   `      Just don't change the structure at all !!!
   `**********************************
SET CHANNEL(12;"")
If (OK=1)
  OPEN WINDOW(Screen width/2-150;Screen height/2-100;Screen width/2+150;Screen height/2+100)
     `Save the database name as a safety feature so
     `you can't restore the wrong database's data accidentally.
  DataBaseName (xDBase)
  MESSAGE("Backing Up  "+xDBase+"."+Char(13))
  SEND VARIABLE(xDBase)
  MESSAGE("Saving Date As :"+String(Current date)+Char(13))
     `Save date and time of the backup.
  xDate:=Current date
  SEND VARIABLE(xDate)
  MESSAGE("Saving Time As :"+Time string(Current time)+Char(13))
  xTime:=Current time
  SEND VARIABLE(xTime)
     `Save the number of files as another precation.  Two databases
     `can have the same name but probably won't have the same number
     `of files.
  GetNumFiles (xFiles)
  MESSAGE("Saving Number Of Files As :"+String(xFiles)+Char(13))
  SEND VARIABLE(xFiles)
  xCount:=1
  While (xCount<=xFiles)
       `ONE MORE SAFETY FEATURE
       `Save the name of each file before the data
       `This one can be a real pain in the (bleep) if you decide to
       `rename files after a backup (I'm really indecisive about file
       `names and other things and I've caused myself problems here). 
    GetFile (xCount;xName)
    MESSAGE("Backing Up File :"+xName+Char(13))
    SEND VARIABLE(xName)
    EXECUTE("ALL RECORDS(["+xName+"])")
    EXECUTE("xSize:=Records in selection(["+xName+"])")
    SEND VARIABLE(xSize)
    EXECUTE("apply to selection(["+xName+"];send record(["+xName+"]))")
    xCount:=xCount+1
  End while 
  CLOSE WINDOW
  SET CHANNEL(11)
End if 

-------------------------------------------------------------
RESTORE
-------------------------------------------------------------

   `**********************************
   `RESTORE Restores All Files Backed Up With BACKUP
   `Kenneth A. Craig
   `Information Management Inc.
   `376 Oakdale Rd
   `Atlanta, GA  30307
   `(404) 523-1132
   `CIS 76210,16
   `GEnie K.CRAIG
   `Be sure you have the externals DataBaseName, GetNumFiles, GetFileName
   `   available in either the System Folder or the Application folder as "proc.ext"
   `   or installed into the Database.res file.
   `------------------------------------------------
   `NOTE : DO NOT rename the database or any files, or
   `      change the fields in any of the files or the the
   `      file will not RESTORE properly.
   `      Just don't change the structure at all !!!
   `**********************************
SET CHANNEL(10;"")
If (OK=1)
  OPEN WINDOW(Screen width/2-150;Screen height/2-100;Screen width/2+150;Screen height/2+100)
     `Get the name of the backed up database and compare
     `it to the current name.  If different then quit the backup.
  DataBaseName (xDBase)
  RECEIVE VARIABLE(yDBase)
  If (xDBase=yDBase)
    MESSAGE("Restoring "+xDBase+"."+Char(13))
    RECEIVE VARIABLE(xDate)
    RECEIVE VARIABLE(xTime)
       `Now compare the number of files in the database.  This could be removed
       `if you want to add and delete files, as long as you keep the file names
       `in the backup file and use them in the restore (see below) and don't change
       `the file names.  The order of files doesn't matter in this backup so this would
       `not be too difficult to do.
    GetNumFiles (xFiles)
    RECEIVE VARIABLE(yFiles)
    If (xFiles=yFiles)
      CONFIRM("Backup Date :"+String(xDate)+Char(13)+"Backup Time :"+Time string(xTime)+Char(13)+"Restore Data?")
      If (OK=1)
        xCount:=1
        While (xCount<=xFiles)
             `Get the file name and number of records backed up.          
          RECEIVE VARIABLE(xName)
          RECEIVE VARIABLE(xSize)
          MESSAGE("Restoring File :"+xName+"  -  "+String(xSize)+" Records."+Char(13))
          Flush:=0
          BEEP(5)
          BEEP(5)
             `Lets you delete the current data or just append the back up data.
          CONFIRM("Delete All Records Of "+xName+" Before Restoring?")
          If (OK=1)
            EXECUTE("ALL RECORDS(["+xName+"])")
            EXECUTE("delete selection(["+xName+"])")
          End if 
          xIndex:=1
          While (xIndex<=xSize)
            EXECUTE("create record(["+xName+"])")
            EXECUTE("receive record(["+xName+"])")
            EXECUTE("save record(["+xName+"])")
            xIndex:=xIndex+1
          End while 
          Flush:=1
          xCount:=xCount+1
        End while 
      End if 
    Else 
      ALERT("The file structure has changed and this is no longer valid backup data.")
    End if 
  Else 
    ALERT("This is a backup file for the database "+yDBase+".")
  End if 
  CLOSE WINDOW
  SET CHANNEL(11)
End if 


